package com.kinyx.framework.db.sentence.str;

import java.util.ArrayList;
import java.util.List;

import com.kinyx.framework.annotation.assist.Tester;
import com.kinyx.framework.bean.StringFormatter;
import com.kinyx.framework.db.sentence.defines.UpdateSentence;
import com.kinyx.framework.enums.impl.ErrorCodeX;
import com.kinyx.framework.exception.KRuntimeException;
import com.kinyx.framework.utils.KListUtils;

import lombok.AccessLevel;
import lombok.RequiredArgsConstructor;

/**
 * 更新语句
 */
@RequiredArgsConstructor(access = AccessLevel.PACKAGE)
@Tester("com.kinyx.framework.db.sentence.str.demo.update.UPDATE_Tester")
public class UPDATE extends _CRUD implements UpdateSentence {

	/** 表子句 */
	private final String table;

	// ================================================================= sets ================================================================= //
	/** 更新条件表达式 */
	private final List<ColumnParam> sets = new ArrayList<>();

	/**
	 * 新增SET值
	 * @param column 列
	 * @param param 参数
	 * @return 本对象
	 */
	public UPDATE set(final String column, final Object param) {
		this.sets.add(new ColumnParam(column, param));
		return this;
	}

	/**
	 * 是否设置过值
	 * @return true：设置过值；false：未设置过值；
	 */
	public boolean isEmpty() {
		return this.sets.isEmpty();
	}

	// ================================================================= WHERE ================================================================= //
	/** WHERE子句 */
	private SQL whereCodition;

	/**
	 * 追加WHERE子句
	 * @param condition 条件子句 
	 * @return 本对象
	 */
	public UPDATE where(final SQL condition) {
		if (this.whereCodition != null) { throw new KRuntimeException(ErrorCodeX.RepeatCall); }
		this.whereCodition = condition;
		return this;
	}

	// ================================================================= 实现方法 ================================================================= //
	@Override
	public String getSentence() {
		return StringFormatter.of()//
				.x("UPDATE %s", this.table)//
				.x(" SET %s", () -> {
					if (UPDATE.this.sets.isEmpty()) { return StringFormatter.Type.Ignore; }
					return KListUtils.join(this.sets, ", ", (set, index) -> { return set.getColumn() + " = ?"; });
				})//
				.x(" %s", () -> {
					if (UPDATE.this.whereCodition == null) { return StringFormatter.Type.Ignore; }
					return "WHERE " + this.whereCodition.getSentence();
				}).format();
	}

	@Override
	public List<Object> getParams() {
		final List<Object> params = new ArrayList<>();
		// sets params
		this.sets.forEach(set -> params.add(set.getParam()));
		// WHERE params
		if (this.whereCodition != null) {
			params.addAll(this.whereCodition.getParams());
		}
		return params;
	}

}
